package com.houweishi.module.currency.service.impl;

import com.alibaba.fastjson.JSON;
import com.houweishi.common.constant.Constants;
import com.houweishi.common.constant.HttpStatus;
import com.houweishi.common.core.domain.AjaxResult;
import com.houweishi.common.core.domain.entity.SysUser;
import com.houweishi.common.core.domain.model.LoginUser;
import com.houweishi.common.exception.base.BaseException;
import com.houweishi.common.utils.DateUtils;
import com.houweishi.common.utils.SecurityUtils;
import com.houweishi.module.bizSerialNum.service.IBizSerialNumTService;
import com.houweishi.module.copy.domain.BizCopy;
import com.houweishi.module.copy.mapper.BizCopyMapper;
import com.houweishi.module.currency.domain.OaCurrency;
import com.houweishi.module.currency.domain.OaCurrencyApproval;
import com.houweishi.module.currency.mapper.OaCurrencyMapper;
import com.houweishi.module.currency.service.IOaCurrencyService;
import com.houweishi.module.record.domain.BizApprovalRecord;
import com.houweishi.module.record.mapper.BizApprovalRecordMapper;
import com.houweishi.module.record.service.IBizApprovalRecordService;
import com.houweishi.system.mapper.SysUserMapper;
import com.houweishi.ws.po.Message;
import com.houweishi.ws.service.WebSocketServer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 通用申请事项管理Service业务层处理
 *
 * @author houweishi
 * @date 2023-02-21
 */
@Service
public class OaCurrencyServiceImpl implements IOaCurrencyService {
    private static final Logger LOGGER = LoggerFactory.getLogger(OaCurrencyServiceImpl.class);

    @Resource
    private OaCurrencyMapper oaCurrencyMapper;

    @Resource
    private BizApprovalRecordMapper bizApprovalRecordMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private BizCopyMapper bizCopyMapper;

    /**
     * 生成流水单号Service
     */
    @Resource
    private IBizSerialNumTService iBizSerialNumTService;

    /**
     * 消息推送Server
     */
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 审批记录Service
     */
    @Resource
    private IBizApprovalRecordService iBizApprovalRecordService;

    /**
     * 查询通用申请事项管理
     *
     * @param currencyId 通用申请事项管理主键
     * @return 通用申请事项管理
     */
    @Override
    public OaCurrency selectOaCurrencyByCurrencyId(Long currencyId) {
        OaCurrency oaCurrency = oaCurrencyMapper.selectOaCurrencyByCurrencyId(currencyId);
        // 根据条件查询审批记录列表
        selectApprovalRecordList(oaCurrency);
        return oaCurrency;
    }

    /**
     * 查询通用申请事项管理列表
     *
     * @param oaCurrency 通用申请事项管理
     * @return 通用申请事项管理
     */
    @Override
    public List<OaCurrency> selectOaCurrencyList(OaCurrency oaCurrency) {
        List<OaCurrency> list = oaCurrencyMapper.selectOaCurrencyList(oaCurrency);

        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(currency -> {
                // 根据条件查询审批记录列表
                selectApprovalRecordList(currency);
            });
        }
        return oaCurrencyMapper.selectOaCurrencyList(oaCurrency);
    }

    /**
     * 新增通用申请事项管理
     *
     * @param oaCurrency 通用申请事项管理
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertOaCurrency(OaCurrency oaCurrency) {
        // 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            return new AjaxResult(HttpStatus.UNAUTHORIZED, "请先登录");
        }
        // 判断是否再提交
        if (StringUtils.isNotBlank(oaCurrency.getSerialNum())) {
            oaCurrency.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            oaCurrency.setUpdateBy(loginUser.getUsername());
            // 修改报销单，审批记录表，抄送
            return resubmitReimburse(oaCurrency, loginUser);
        } else {
            // 获取流水单号
            String serialNum = iBizSerialNumTService.generateSerialNum("TYSQ");
            oaCurrency.setSerialNum(serialNum);
            oaCurrency.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
            int result = oaCurrencyMapper.insertOaCurrency(oaCurrency);
            if (result < 1) {
                return new AjaxResult(HttpStatus.ERROR, "新增通用申请事项管理失败");
            }
            // 插入审批记录表
            return setApprovalRecord(oaCurrency, loginUser);
        }
    }

    /**
     * 重提交：修改报销单，审批记录表，抄送
     * @param oaCurrency
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult resubmitReimburse(OaCurrency oaCurrency,LoginUser loginUser) {
        //修改报销单
        oaCurrencyMapper.updateOaCurrency(oaCurrency);
        //删除审批记录
        bizApprovalRecordMapper.deleteBizApprovalRecordBySerialNum(oaCurrency.getSerialNum());
        // 删除抄送
        bizCopyMapper.deleteBizCopyMapperBySerialNum(oaCurrency.getSerialNum());
        //新增审批及抄送
        return setApprovalRecord(oaCurrency,loginUser);
    }

    /**
     * 修改通用申请事项管理
     *
     * @param oaCurrency 通用申请事项管理
     * @return 结果
     */
    @Override
    public int updateOaCurrency(OaCurrency oaCurrency) {
        oaCurrency.setUpdateTime(DateUtils.getNowDate());

        // 先删后增
        oaCurrencyMapper.deleteBizApprovalRecord(oaCurrency);
        // 插入审批记录表
        setApprovalRecord(oaCurrency, null);
        return oaCurrencyMapper.updateOaCurrency(oaCurrency);
    }

    /**
     * 批量删除通用申请事项管理
     *
     * @param currencyIds 需要删除的通用申请事项管理主键
     * @return 结果
     */
    @Override
    public int deleteOaCurrencyByCurrencyIds(Long[] currencyIds) {
        return oaCurrencyMapper.deleteOaCurrencyByCurrencyIds(currencyIds);
    }

    /**
     * 删除通用申请事项管理信息
     *
     * @param currencyId 通用申请事项管理主键
     * @return 结果
     */
    @Override
    public int deleteOaCurrencyByCurrencyId(Long currencyId) {
        return oaCurrencyMapper.deleteOaCurrencyByCurrencyId(currencyId);
    }

    /**
     * 查询通用申请事项管理列表（含业务表状态）
     * @param oaCurrency
     * @return
     */
    @Override
    public List<OaCurrencyApproval> selectOaCurrencyApprovalList(OaCurrency oaCurrency) {
        return oaCurrencyMapper.selectOaCurrencyApprovalList(oaCurrency);
    }


    /**
     * 根据条件查询审批记录列表
     *
     * @param oaCurrency
     */
    void selectApprovalRecordList(OaCurrency oaCurrency) {
        // 三个条件定位准确的数据
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        bizApprovalRecord.setApplicationId(oaCurrency.getCurrencyId());
        bizApprovalRecord.setUserId(oaCurrency.getUserId());
        bizApprovalRecord.setSubscribePatternId(oaCurrency.getSubscribePatternId());

        List<BizApprovalRecord> list = bizApprovalRecordMapper.selectBizApprovalRecordList(bizApprovalRecord);
        oaCurrency.setApprovalRecordList(list);

        // 三个条件定位准确的数据（抄送）
        BizCopy bizCopy = new BizCopy();
        bizCopy.setApplicationId(oaCurrency.getCurrencyId());
        bizCopy.setUserId(oaCurrency.getUserId());
        bizCopy.setSubscribePatternId(oaCurrency.getSubscribePatternId());

        List<BizCopy> list2 = bizCopyMapper.selectBizCopyList(bizCopy);
        oaCurrency.setBizCopyList(list2);
    }


    /**
     * 插入审批记录表
     *
     * @param oaCurrency
     */
    @Transactional(rollbackFor = Exception.class)
    AjaxResult setApprovalRecord(OaCurrency oaCurrency, LoginUser loginUser) {
        List<BizApprovalRecord> list;
        if ("0".equals(oaCurrency.getTypeStatus())){
            list = iBizApprovalRecordService.approvalTemplate(loginUser,oaCurrency.getSerialNum(),"通用");
        }else{
            list = addApprovalRecord(oaCurrency,loginUser);
        }
        bizApprovalRecordMapper.insertBatchBizApprovalRecord(list);
        // 增加抄送人
        addCopyPeople(oaCurrency);

        // 推送消息
        List<BizApprovalRecord> messageList = list.stream()
                .filter(a -> a.getSequence() == 2)
                .collect(Collectors.toList());
        sendMessage(messageList.get(0).getApproverId(), messageList.get(0).getApproverName(), oaCurrency);
        return new AjaxResult(HttpStatus.SUCCESS, "新增通用申请事项管理审批记录成功");
    }

    /**
     * 自定义审批人
     * @param oaCurrency
     * @param loginUser
     * @return
     */
    public List<BizApprovalRecord> addApprovalRecord(OaCurrency oaCurrency, LoginUser loginUser){
        List<BizApprovalRecord> list = new ArrayList<>();
        int sequence = 1;
        // 保存发起人
        BizApprovalRecord initiatorRecord = createApprovalRecord(oaCurrency, null, loginUser);
        initiatorRecord.setSequence(sequence);
        initiatorRecord.setSerialNum(oaCurrency.getSerialNum());
        initiatorRecord.setApprovalStatus(Constants.COMPLETED);
        initiatorRecord.setTypeOperation(Constants.AGREE);
        initiatorRecord.setBusinessStatus(Constants.APPROVE);
        list.add(initiatorRecord);
        // 字符串分割，并把String[]转换为list(传入了一个字符串类型的数据）
        if (StringUtils.isEmpty(oaCurrency.getApprover())) {
            throw new BaseException("请选择新增通用申请事项管理审批人");
        }
        String[] approvers = oaCurrency.getApprover().split(",");
        List<Long> idList = Arrays.stream(approvers).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        // 获取详细审批人信息
        List<SysUser> sysUserList = sysUserMapper.selectUserByUserIds(idList);
        if (idList.size() != sysUserList.size()) {
            throw new BaseException("新增通用申请事项管理审批人有误");
        }
        Long userId = null;
        String userName = null;
        // 根据职位级别降级排序
        sysUserList.sort(Comparator.comparingLong(SysUser::getPositionLevel).reversed());
        // 增加审批记录
        if (!CollectionUtils.isEmpty(sysUserList)) {
            for (int i = 0; i < sysUserList.size(); i++) {
                SysUser sysUser = sysUserMapper.selectUserById(sysUserList.get(i).getUserId());
                BizApprovalRecord approvalRecord = createApprovalRecord(oaCurrency, sysUser, null);
                if (i == 0) {
                    userId = sysUser.getUserId();
                    userName = sysUser.getUserName();
                    approvalRecord.setApprovalStatus(Constants.APPROVE);
                } else {
                    approvalRecord.setApprovalStatus(Constants.NOT_APPROVED);
                }
                sequence++;
                approvalRecord.setSequence(sequence);
                list.add(approvalRecord);
            }
        }
        return list;
    }

    /**
     * 推送消息到前端
     *
     * @param userId
     * @param userName
     * @param oaCurrency
     */
    private void sendMessage(Long userId, String userName, OaCurrency oaCurrency) {
        try {
            // 发送消息
            Message message = new Message();
            message.setFromId(oaCurrency.getUserId());
            message.setFromName(oaCurrency.getUsername());
            message.setNextNodeId(userId);
            message.setNextNodeName(userName);
            message.setStatus(Constants.COMPLETED);
            message.setSerialNum(oaCurrency.getSerialNum());
            message.setType(oaCurrency.getSubscribePatternName());
            webSocketServer.onMessage(JSON.toJSONString(message));
        } catch (Exception e) {
            LOGGER.error("通用申请事项管理消息推送失败", e);
        }
    }

    /**
     * 添加抄送人
     *
     * @param oaCurrency
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void addCopyPeople(OaCurrency oaCurrency) {
        if (StringUtils.isNoneBlank(oaCurrency.getCopyerId())) {
            // 字符串分割，并把String[]转换为list，（抄送人id）
            String[] copyerIds = oaCurrency.getCopyerId().split(",");
            List<String> copyerIdList = Arrays.stream(copyerIds).collect(Collectors.toList());
            // 抄送记录表
            if (!CollectionUtils.isEmpty(copyerIdList)) {
                copyerIdList.forEach(id -> {
                    BizCopy bizCopy = new BizCopy();
                    SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(id));

                    bizCopy.setApplicationId(oaCurrency.getCurrencyId());
                    bizCopy.setCopyerId(sysUser.getUserId());
                    bizCopy.setCopyerName(sysUser.getUserName());
                    bizCopy.setPositionLevel(sysUser.getPositionLevel());
                    bizCopy.setUserId(oaCurrency.getUserId());
                    bizCopy.setUsername(oaCurrency.getUsername());
                    bizCopy.setSerialNum(oaCurrency.getSerialNum());
                    bizCopy.setSubscribePatternId(oaCurrency.getSubscribePatternId());
                    bizCopy.setSubscribePatternName(oaCurrency.getSubscribePatternName());
                    bizCopy.setCopyerStatus("0");
                    bizCopy.setCreateTime(DateUtils.getNowDate());
                    bizCopyMapper.insertBizCopy(bizCopy);
                });
            }
        }
    }

    /**
     * 设置审批记录信息
     *
     * @param oaCurrency
     * @param sysUser
     * @return
     */
    public BizApprovalRecord createApprovalRecord(OaCurrency oaCurrency, SysUser sysUser, LoginUser loginUser) {
        BizApprovalRecord bizApprovalRecord = new BizApprovalRecord();
        if (null != sysUser) {
            bizApprovalRecord.setApproverId(sysUser.getUserId());
            bizApprovalRecord.setApproverName(sysUser.getUserName());
            bizApprovalRecord.setPositionLevel(sysUser.getPositionLevel());
        }
        if (null != loginUser) {
            bizApprovalRecord.setApproverId(loginUser.getUserId());
            bizApprovalRecord.setApproverName(loginUser.getUsername());
        }
        bizApprovalRecord.setSubscribePatternName("通用");
        bizApprovalRecord.setSerialNum(oaCurrency.getSerialNum());
        bizApprovalRecord.setApplicationId(oaCurrency.getCurrencyId());
        bizApprovalRecord.setUserId(oaCurrency.getUserId());
        bizApprovalRecord.setUsername(oaCurrency.getUsername());
        bizApprovalRecord.setSubscribePatternId(oaCurrency.getSubscribePatternId());
        bizApprovalRecord.setSubscribePatternName(oaCurrency.getSubscribePatternName());
        bizApprovalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        bizApprovalRecord.setUpdateBy(oaCurrency.getUsername());
        bizApprovalRecord.setCreateBy(oaCurrency.getUsername());
        bizApprovalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return bizApprovalRecord;
    }

}
